<?php
namespace DataWidget\widget;

use DataWidget\entity\ActionLink;
use DataWidget\list_item\ListItem;
use DataWidget\field\TimeField;
use DataWidget\field\SelectField;
use DataWidget\field\Field;

class ListWidget
{
    public $map=[
        "text"=>["input"=>Input::class, "field"=>Field::class],
        "datetime"=>["input"=>DateTimeInput::class, "field"=>TimeField::class, "format"=>"Y-m-d H:i"],
        "select"=>["input"=>SelectInput::class, "field"=>SelectField::class],
    ];
    public function loadItem($data)
    {
        $item_class=ListItem::class;
        $field_class=Field::class;
        if( isset($data["type"]) && isset($this->map[$data["type"]]) ){
            $info = $this->map[$data["type"]];
            if(is_string($info)) $item_class = $info;
            else{
                if(isset($info["list"])) $item_class=$info["list"];
                if(isset($info["field"])) $field_class=$info["field"];
                $data=array_merge($data,$info);
            }
        }
        return $item_class::fromArray($data,$field_class);
    }

    static public function alloc()
    {
        return new static;
    }
    public function setMap($map)
    {
        $this->map=$map;
        return $this;
    }

    /**
     * action操作
     * 可对列表中的一条数据执行的操作
     * 对于不同的数据，可以执行的操作也可以不同，如果需要，用actions_cb进行控制
     * @var Action[] $actions 可对列表中的一条数据执行的操作的列表
     * @var callable $actions_cb 生成操作列表的回调函数
     */
    public $actions=[];
    public $actions_cb=null;
    /**
     * 设置生成操作列表的回调函数
     * @var callable $action function($item):Action[]
     */
    public function setItemActions($callback)
    {
        $this->actions_cb=$callback;
        return $this;
    }
    /**
     * 添加单个操作
     * @param string $title
     * @param string|callable $href 链接,允许传入一个回调函数，用来在被调用时返回实际的链接
     * @param false|string $confirm 是否需要确认以及需要确认时的提示语
     */
    public function addAction($title,$href,$confirm=false)
    {
        $this->actions[]=ActionLink::create($title,$href,$confirm);
        return $this;
    }
    
    /**
     * flag标记
     * 允许添加页面模板支持的flag，用来启用相关的功能
     * 主要不要与其他字段冲突
     */
    /** @var string[] $flags */
    public $flags=[];
    public function setFlags($list)
    {
        $this->flags=$list;
        return $this;
    }
    public function addFlag($flag)
    {
        $this->flags[]=$flag;
        return $this;
    }

    public $fields=[];
    public function loadFields($data)
    {
        $this->fields=$data;
        return $this;
    }

    /** @var string $primary 主键的code */
    public $primary="id";
    public function setPrimary($code)
    {
        $this->primary=$code;
        return $this;
    }

    public $data=[];
    public function setData($data)
    {
        $this->data=$data;
        return $this;
    }

    public function toArray()
    {
        $data=$this->data;
        //初始化各字段
        $fields=[];
        foreach($this->fields as $key => $field){
            if(!$this->hide_items || !in_array($field["code"], $this->hide_items)){
                $fields[$key] = $this->loadItem($field,ListItem::class);
            }
            else{
                unset($this->fields[$key]);
            }
        }
        //调整各条记录的值
        /** @var ListItem $field */
        foreach($data as $key => $item){
            foreach($fields as $field){
                if(isset($data[$key][$field->code])){
                    $data[$key][$field->code] = $field->stringifyValue($data[$key][$field->code]);
                }
                else $data[$key][$field->code] = "";
            }
        }
        //调整各条记录的操作
        foreach($data as $key => $item){
            $actions=[];

            foreach($this->actions as $action){
                $action_arr=$action->toArray();
                if(is_callable($action->href)){
                    $cb=$action->href;
                    $action_arr["href"]=$cb($item);
                }
                elseif(is_string($action->href)){
                    $action_arr["href"]=$action->href;
                }
                $actions[]=$action_arr;
            }

            if($this->actions_cb){
                $cb=$this->actions_cb;
                $cb_actions=$cb($item);
                foreach($cb_actions as $item_action){
                    $actions[]=$item_action->toArray();
                }
            }
            $data[$key]["actions"]=$actions;
        }

        $arr=[
            "primary"=>$this->primary,
            "fields"=>$this->fields,
            "data"=>$data,
        ];
        foreach($this->flags as $flag){
            $arr[$flag]=true;
        }

        return $arr;
    }
    /** @var string[] $hide_items */
    protected $hide_items=[];
    public function setHideItems($codes = '')
    {
        if(!$codes) $this->hide_items = [];
        else{
            $this->hide_items = explode(",", $codes);
        }
        return $this;
    }
    public function setShowItems($codes = '')
    {
        if(!$codes) $this->hide_items = [];
        else{
            $items = [];
            $codes = explode(",", $codes);
            foreach($this->fields as $field){
                if(!in_array($field["code"],$codes)){
                    $items[] = $field["code"];
                }
            }
            $this->hide_items = $items;
        }
        return $this;
    }
}
